package xj.graph2d.app;

import static xj.app.BaseApplicationFrame.getResourceString;

import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

import org.jdesktop.swingx.JXTitledPanel;

import xj.app.DrawToolkit;
import xj.graph2d.Document;
import xj.graph2d.DocumentConstants;
import xj.graph2d.GraphDocument;
import xj.graph2d.SimpleDrawDocument;
import xj.graph2d.SimpleDrawView;
import xj.graph2d.View;
import xj.graph2d.tools.StencilTool;

public class StencilPanel 
  extends JPanel 
  implements DecoratedComponent {

  public static final float MINIMUM_WIDTH = 400; 
  public static final float MINIMUM_HEIGHT = 400; 

  public StencilPanel(DrawApp main) {
    this.main = main; 
    setLayout(cardLayout = new CardLayout());
    toolkit = new DrawToolkit(1);
    toolkit.addTool(new StencilTool(main, this));
  }

  public void addStencil(String name, View view) { 
    //System.out.println("StencilPanel.addStencil() " + name);
    if (view != null && name != null) { 
      view.setDrawToolkit(toolkit);      
      add(view, name);
      activateView();
    }
  }

  public JComponent[] makeTitleDeco() { 
    Icon prevIcon = DrawApp.getIcon("jdePrevIcon");
    Icon nextIcon = DrawApp.getIcon("jdeNextIcon");
    prevButton = new JButton(prevIcon); 
    nextButton = new JButton(nextIcon); 
    ActionListener act = new ActionListener() { 
	public void actionPerformed(ActionEvent e) { 
	  Object src = e.getSource();
	  if (src == prevButton) { 
	    cardLayout.previous(StencilPanel.this);
	    activateView();
	  } else if (src == nextButton) { 
	    cardLayout.next(StencilPanel.this);
	    activateView();
	  }
	}
      };
    prevButton.addActionListener(act);
    prevButton.setToolTipText("previous stencil"); 
    nextButton.addActionListener(act);
    nextButton.setToolTipText("next stencil"); 
    return new JComponent[] { prevButton, nextButton }; 
  }

  public String getCurrentStencilName() { 
    return curStencilName; 
  }

  public void activateView() { 
    int n = getComponentCount();
    int i = 0;
    for (; i < n; i++) {
      Component comp = getComponent(i);
      if (comp.isVisible() && 
	  comp instanceof View) { 
	View view = (View) comp;
	view.setDrawToolkit(toolkit);      
	view.activateView();
	curStencil = view;
	curStencilName = getStencilName(view);
	break;
      }
    }

    //System.out.println("StencilPanel.activateView() curStencilName=" + curStencilName);

    // update title
    JXTitledPanel tpanel = main.getJXTitledPanel("Stencils");
    if (tpanel != null) { 
      tpanel.setTitle(getResourceString("Stencils.Panel.title") + " [" + (i+1) + "/" + n + "]");
    }
  }

  void loadStencil(String name) { 
    //System.out.println("StencilPanel.loadStencil() name=" + name);

    if (name != null) { 
      String userhome = System.getProperty("user.home");
      String appDir = main.getAppDir();
      String stencilDir = (userhome + File.separator + appDir + 
			   File.separator + DrawApp.STENCIL_DIR);
      String filename = (stencilDir  + File.separator + name + 
			 "." + DrawApp.stencilFileExtension);

      SimpleDrawView mainView = main.view;
      SimpleDrawDocument mainDoc = main.doc;
      try { 
	View old = main.stencils.get(name); 
	main.initDocView(); 
	SimpleDrawView view = main.view;
	SimpleDrawDocument doc = main.doc;
	doc.openFile(filename, DocumentConstants.XML_STENCIL_FILE_TYPE); 
	DrawApp.fitCanvas(view, MINIMUM_WIDTH, MINIMUM_HEIGHT);
	main.stencils.put(name, view); 
	view.setStencilMode(true);
	view.setShowRuler(false);
	view.setShowMargin(false);
	view.setScaleFactor(0.5f);

	if (old != null) { 
	  // remove existing stencil
	  remove(old);
	}
	addStencil(name, view);
	cardLayout.show(this, name);
	view.activateView();
	curStencil = view;
	curStencilName = name;
	activateView();
      } catch (IOException ex) { 
	ex.printStackTrace();
      } catch (xj.graph2d.DocumentException ex) { 
	ex.printStackTrace();
      } finally { 
	main.doc = mainDoc;
	main.view = mainView;
      }
    }
  }
  
  boolean hasStencil(String name) { 
    return main.stencils.keySet().contains(name);
  }

  String getStencilName(View s) { 
    //System.out.println("StencilPanel.getStencilName() enter");
    if (s != null) { 
      Set<Map.Entry<String, View>> eset = main.stencils.entrySet();
      Iterator<Map.Entry<String, View>> iter = eset.iterator();
      while (iter.hasNext()) {
	Map.Entry<String, View> entry = iter.next();	
	//System.out.println("StencilPanel.getStencilName() key=" + entry.getKey());
	if (entry.getValue() == s) { 
	  return entry.getKey();
	}
      }
    }
    return null;
  }

  public void editCurrentStencil() {
    if (openedStencils.contains(curStencilName)) { 
      main.showViewTab(curStencilName);
    } else { 
      String userhome = System.getProperty("user.home");
      String appDir = main.getAppDir();
      String stencilDir = (userhome + File.separator + appDir + 
			   File.separator + DrawApp.STENCIL_DIR);
      String stencilFilename = (stencilDir  + File.separator + 
				curStencilName + "." + DrawApp.stencilFileExtension);

      try { 
	main.loadFile(stencilFilename, curStencilName, DocumentConstants.XML_STENCIL_FILE_TYPE);
	openedStencils.add(curStencilName);
      } catch (java.io.IOException ex) { 
	ex.printStackTrace();
      } catch (xj.graph2d.DocumentException ex) { 
	ex.printStackTrace();
      }
    }
  }

  public void deleteCurrentStencil() {
    int n = getComponentCount();
    if (n > 1) { 
      remove(curStencil);
      main.stencils.remove(curStencilName);
      activateView();
    }
  }

  public void closeStencilEditing(String name) { 
    if (name != null) { 
      openedStencils.remove(name);
    }
  }

  public void initStencil() { 
    String name = "ClassDiagramStencil";
    String userhome = System.getProperty("user.home");
    String appDir = main.getAppDir();
    String stencilDir = (userhome + File.separator + appDir + 
			 File.separator + DrawApp.STENCIL_DIR);
    String filename = (stencilDir  + File.separator + name + 
		       "." + DrawApp.stencilFileExtension);

    //System.out.println("StencilPanel.initStencil() name=" + name + " filename=" + filename);

    SimpleDrawView mainView = main.view;
    SimpleDrawDocument mainDoc = main.doc;
    main.initDocView(); 
    SimpleDrawView view = main.view;
    SimpleDrawDocument doc = main.doc;
    doc.setFilename(filename);
    doc.setName(name);
    doc.setNamespace(main.getNamespaceURI(), main.getNamespacePrefix());
    doc.setDocumentType(Document.DocumentType.UML_Class_Diagram);
    doc.setFiletype(DocumentConstants.XML_STENCIL_FILE_TYPE);
    if (doc instanceof GraphDocument) {
      GraphDocument gdoc = (GraphDocument) doc;
      gdoc.initModel();
    }    

    try { 
      main.saveFile(doc, false);      
    } catch (IOException ex) { 
      ex.printStackTrace();
    } catch (xj.graph2d.DocumentException ex) { 
      ex.printStackTrace();
    }

    view.setStencilMode(true);
    view.setShowRuler(false);
    view.setShowMargin(false);
    view.setScaleFactor(0.5f);
    DrawApp.fitCanvas(view, MINIMUM_WIDTH, MINIMUM_HEIGHT);
    main.stencils.put(name, view); 

    addStencil(name, view);
    cardLayout.show(this, name);
    view.activateView();
    curStencil = view;
    curStencilName = name;
    activateView();

    main.doc = mainDoc;
    main.view = mainView;
  }


  protected DrawApp main;
  protected JButton prevButton, nextButton; 
  protected CardLayout cardLayout; 

  protected View   curStencil = null;
  protected String curStencilName = null;

  protected DrawToolkit toolkit;

  protected Set<String> openedStencils = new HashSet<String>();

}

